package com.cskaoyan.javase.object._1getclass;

import sun.rmi.transport.ObjectTable;

/**
 * getClass方法
 * 1.方法的声明
 *      public final native Class<?> getClass();
 *      该方法没有权限问题，可以随意调用它
 *      其次该方法被final修饰表示该方法虽然能够被子类继承，但是不能被重写。只能用，并不能改
 *      native表示改方法是一个本地方法，表示该方法的实现不是Java代码完成的。
 *      Class<?> 处在方法返回值类型的位置，Class是一个类，表示该方法返回Class对象
 *          <?>是泛型，但是Java的泛型是伪泛型，Java的泛型不影响代码运行，而只影响代码编译。
 *          那么在今天，我们直接去掉泛型，不影响代码运行。
 *      而且注意该方法是无参的。
 *
 * 2.方法的作用
 *      通过一个本地方法的实现，去获取Class对象。
 *      所以接下来的问题，主要是：
 *          1.什么是Class对象？
 *          2.Class类是什么？它又有什么作用？
 * 接下来，我们就主要来研究一下Class类和它的对象。
 *
 * 为了实现程序员在程序运行期间动态获取类型信息，动态实现操作的需求,
 * （类加载 大的过程 三步  加载 --> 连接 -->初始化）
 * 其中加载的过程，JVM就在堆上创建了Class对象
 * JVM在类加载某个类时,会在堆上创建一个封装了这个类类型信息的一个对象,即Class对象
 * 这个Class对象中,就存储了这个类的类型信息。
 * 获取类的Class对象，就是获取类的类型信息。
 *
 * 注意事项：
 *      1.getClass方法不是创建Class对象，Class对象是类加载某个类的过程中，JVM创建的。
 *          getClass方法只不过是获取这个Class对象，然后用引用指向这个对象。
 *      2.Class对象也称之为某个类的运行时对象，或者运行时类对象，简称"类对象"
 *          因为它的作用是在程序的运行期间 获取该类的类型信息
 *          反射实际上就是依赖于Class对象的，反射就是Class类 API 的使用。
 *          实际开发中反射获取Class对象的方式并不是getClass。
 *      3.getClass方法获取Class对象并不是实际开发中常用的做法
 *          getClass方法在实际开发中比较常用的场景是判断两个引用所指向的对象，是否是同一种类型的对象。
 *          某个类的类加载只有一次，那么某个类的Class对象也是唯一的，只有一个。
 *          这是Class对象非常重要的特点。
 *
 *          所以根据这一个特点：
 *              双等号连接两个引用.getClass()
 *              如果是同一种类型，那就返回true
 *              否则返回false
 *         注意：
 *              不要给引用的数据类型加上泛型，因为泛型影响编译，会导致双等号无法连接。
 *
 * @since 09:49
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        Student s = new Student();
        Student s2 = new Student();
        Class stuClazz = s.getClass();
        Class stuClazz2 = s2.getClass();
        System.out.println(stuClazz == stuClazz2);

        Teacher t = new Teacher();
        Class teacherClazz = t.getClass();
        System.out.println(stuClazz == teacherClazz);

        // 获取简单类名
        System.out.println(stuClazz.getSimpleName());
        // 获取全限定类名
        System.out.println(stuClazz.getName());


        Class<? extends Student> stu = s.getClass();
        Class<? extends Teacher> teacher = t.getClass();
        // System.out.println(stu == teacher);

        // System.out.println(s.getClass() == t.getClass());
        Object o = s;
        Object o1 = t;
        System.out.println(o.getClass() == o1.getClass());


    }

    public static boolean judge(Object o1, Object o2) {
        return o1.getClass() == o2.getClass();
    }

}

class Student {
    // 判断两个引用所指向的对象是否是同种类型
    public boolean judgeDataType(Object o) {
        return this.getClass() == o.getClass();
    }
}

class Teacher {
}